﻿// owner 蒋家伟

#pragma once

// jsdk
#include "JsonUtils.h"
#include "CommonFieldDescriptor.h"
#include "Dbg_Warn_Define.h"
#include "DBSet.h"

namespace jsdk
{
    // 类别描述 : DBSet字段描述，存储BaseType类型
    template<typename T, bool = is_OwnerPtr<is_DBSet<T>::valueType>::value>
    class SetTypeFieldDescriptor : public CommonFieldDescriptor
    {
        using valueType = T;
        static_assert(jsdk::is_DBSet<valueType>::value, "当前对象不是DBSet");
        using Container_Value_Type = typename jsdk::is_DBSet<valueType>::valueType;
    public:
        /// \ brief 创建类别字段描述符
        /// \ in variableName   变量名称
        /// \ in offset         相对偏移
        /// \ in typeName       类别名称
        SetTypeFieldDescriptor(const std::wstring& variableName, uint64_t offset, const std::wstring& typeName) :
            CommonFieldDescriptor(variableName, offset, typeid(valueType).hash_code(), typeName){}
    private:
        virtual bool serializeValue(JsonDocument& jsonDoc, JsonObject& jsonObject) const noexcept override
        {
            // 按照字节大小流化
            const valueType* pValue =  IClassFieldDescriptor::get<valueType>();
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pValue, CommonFieldDescriptor::getErrorMsgPrefix() + L"获取存储值时发生异常", L"蒋家伟", L"2023-11-30");
            // 创建一个json数组
            JsonArray valueArray = JsonUtils::createArray();

            for (const auto& container_Value : *pValue)
            {
                valueArray.PushBack(JsonUtils::getDataStream(container_Value, jsonDoc), jsonDoc.GetAllocator());
            }

            JsonUtils::insert(jsonDoc, jsonObject, s_pValue_Key, std::move(valueArray));
            return true;
        }

        virtual bool unserializeValue(const JsonObject& jsonObject) noexcept override
        {
            const JsonValue* pJsonValue = JsonUtils::getJsonValue(jsonObject, s_pValue_Key);
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pJsonValue && pJsonValue->IsArray(), CommonFieldDescriptor::getErrorMsgPrefix() + L"容器存储的对象不是数组", L"蒋家伟", L"2023-12-01");
            valueType value;
            for (const auto& jsonValue : pJsonValue->GetArray())
            {
                Container_Value_Type container_Value{};
                bool success = JsonUtils::getValueFromJsonValue(jsonValue, container_Value);
                DBG_WARN_AND_CONTINUE_UNLESS(success, CommonFieldDescriptor::getErrorMsgPrefix() + L"数组存储的值反流失败", L"蒋家伟", L"2023-12-01");
                value.insert(std::move(container_Value));
            }
            return IClassFieldDescriptor::set(value);
        }
    };

    // 类别描述 : DBSet字段描述，存储Ownptr类型
    template<typename T>
    class SetTypeFieldDescriptor<T, true> : public CommonFieldDescriptor
    {
        using valueType = T;
        static_assert(jsdk::is_DBSet<valueType>::value, "当前对象不是DBSet");
        using Container_Value_Type = typename jsdk::is_DBSet<valueType>::valueType;
        using Ownerptr_Value_type = typename jsdk::is_OwnerPtr<Container_Value_Type>::ValueType;
    public:
        /// \ brief 创建类别字段描述符
        /// \ in variableName   变量名称
        /// \ in offset         相对偏移
        /// \ in typeName       类别名称
        SetTypeFieldDescriptor(const std::wstring& variableName, uint64_t offset, const std::wstring& typeName) :
            CommonFieldDescriptor(variableName, offset, typeid(valueType).hash_code(), typeName) {}
    private:
        virtual bool serializeValue(JsonDocument& jsonDoc, JsonObject& jsonObject) const noexcept override
        {
            // 按照字节大小流化
            const valueType* pValue = IClassFieldDescriptor::get<valueType>();
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pValue, CommonFieldDescriptor::getErrorMsgPrefix() + L"获取存储值时发生异常", L"蒋家伟", L"2023-11-30");

            // 创建一个json数组
            JsonArray valueArray = JsonUtils::createArray();
            for (const auto& container_Value : *pValue)
            {
                // 创建一个jsonObject
                JsonObject schemaJsonObject = JsonUtils::createObject();
                if (container_Value != nullptr)
                {
                    const DBSchemaObject* pDBSchemaObject = quick_cast<DBSchemaObject>(container_Value.get());
                    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDBSchemaObject, CommonFieldDescriptor::getErrorMsgPrefix() + L"必须要继承DBSchemaObject才可以序列化", L"蒋家伟", L"2023-11-30");

                    const jsdk::UniqueId& uid = pDBSchemaObject->getClassId();
                    DBG_WARN_AND_RETURN_FALSE_UNLESS(uid.isValid(), CommonFieldDescriptor::getErrorMsgPrefix() + L"不为空，但是获取反射对象UID失败", L"蒋家伟", L"2023-11-30");

                    bool success = pDBSchemaObject->serialize(jsonDoc, schemaJsonObject);
                    DBG_WARN_AND_RETURN_FALSE_UNLESS(success, CommonFieldDescriptor::getErrorMsgPrefix() + L"序列化失败UID:" + uid.toString(), L"蒋家伟", L"2023-11-30");
                }
                else
                {
                    // 空指针，写入空uid
                    JsonUtils::insert(jsonDoc, schemaJsonObject, s_pClassUid_Key, JsonUtils::getDataStream(UniqueId::s_InvalidUId, jsonDoc));
                }
                valueArray.PushBack(std::move(schemaJsonObject), jsonDoc.GetAllocator());
            }

            JsonUtils::insert(jsonDoc, jsonObject, s_pValue_Key, std::move(valueArray));
            return true;
        }

        virtual bool unserializeValue(const JsonObject& jsonObject) noexcept override
        {
            const JsonValue* pJsonValue = JsonUtils::getJsonValue(jsonObject, s_pValue_Key);
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pJsonValue && pJsonValue->IsArray(), CommonFieldDescriptor::getErrorMsgPrefix() + L"容器存储的对象不是集合", L"蒋家伟", L"2023-12-01");
            valueType value;
            for (const auto& jsonObjectValue : pJsonValue->GetArray())
            {
                DBG_WARN_AND_RETURN_FALSE_UNLESS(jsonObjectValue.IsObject(), CommonFieldDescriptor::getErrorMsgPrefix() + L"集合反流对象不是object", L"蒋家伟", L"2023-12-06");
                const JsonObject& jsonObject_InArray = jsonObjectValue.GetObject();

                jsdk::UniqueId typeUid;
                bool success = CommonFieldDescriptor::getClassUidFromJsonObject(jsonObject_InArray, typeUid);
                DBG_WARN_AND_RETURN_FALSE_UNLESS(success, CommonFieldDescriptor::getErrorMsgPrefix() + L"缺少类别描述", L"蒋家伟", L"2023-12-07");

                if (typeUid.isValid())
                {
                    OwnerPtr<jsdk::DBSchemaObject> opDBSchemaObject = ObjectReflectUtils::getObjectReflectImp(typeUid, nullptr);
                    DBG_WARN_AND_RETURN_FALSE_UNLESS(opDBSchemaObject, CommonFieldDescriptor::getErrorMsgPrefix() + L"类别对象无法反射, 其UID:" + typeUid.toString(), L"蒋家伟", L"2023-11-30");
                    const JsonValue* pJsonObjectValue = JsonUtils::getJsonValue(jsonObject_InArray, s_pValue_Key);
                    DBG_WARN_AND_RETURN_FALSE_UNLESS(pJsonObjectValue && pJsonObjectValue->IsObject(), CommonFieldDescriptor::getErrorMsgPrefix() + L"反流对象不是Object, 其UID:" + typeUid.toString(), L"蒋家伟", L"2023-11-30");
                    bool success = opDBSchemaObject->unserialize(*pJsonObjectValue);
                    DBG_WARN_AND_RETURN_FALSE_UNLESS(success, CommonFieldDescriptor::getErrorMsgPrefix() + L"反流对象失败, 其UID为:" + typeUid.toString(), L"蒋家伟", L"2023-11-30");
                    value.insert(transformOwnerShipAndCast<Ownerptr_Value_type>(opDBSchemaObject));
                }
                else
                {
                    DBG_WARN_AND_RETURN_FALSE_UNLESS(JsonUtils::hasMember(jsonObject_InArray, s_pValue_Key) == false, CommonFieldDescriptor::getErrorMsgPrefix() + L"类对象无法识别且有数据对象", L"蒋家伟", L"2023-11-30");
                    value.insert(nullptr);
                }
            }
            return IClassFieldDescriptor::set(value);
        }
    };
}
